using System;
using Basmus.Values;
using Basmus.Values.Attributive;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Basmus.Tests.Values.Attributive
{
    [TestClass]
    public class PropertyInfoBuilderTests
    {
        public class TestModel
        {
            public int NoAttrsProp { get; set; }

            [Name("OtherNameDefaultKey")]
            public double SingleNameAttrDefaultKeyProp { get; set; }

            [Name("Name1", "Key1")]
            [Name("Name2", "Key2")]
            public string MultipleNameAttrsProp { get; set; }
        }

        [TestMethod]
        public void Build_NoAttributesPropertyByPropName_ReturnWithSamePropNameAndType()
        {
            //Arrange
            IPropertyInfoBuilder builder = new PropertyInfoBuilder();
            var modelContext = new ModelContext(typeof(TestModel), SchemeKey.Default);
            var valueContext = new ValuesContext(modelContext, "NoAttrsProp");
            //Act
            var propInfo = builder.Build(valueContext);

            //Assert
            var expected = Tuple.Create("NoAttrsProp", typeof (int));
            Assert.AreEqual(expected, Tuple.Create(propInfo.Name, propInfo.PropertyType));
        }

        [TestMethod]
        public void Build_SingleNameAttrDefaultKeyPropertyByPropName_ReturnCorrespondingWithPropNameAndName()
        {
            //Arrange
            IPropertyInfoBuilder builder = new PropertyInfoBuilder();
            var modelContext = new ModelContext(typeof(TestModel), SchemeKey.Default);
            var valueContext = new ValuesContext(modelContext, "SingleNameAttrDefaultKeyProp");
            //Act
            var propInfo = builder.Build(valueContext);

            //Assert
            var expected = Tuple.Create("SingleNameAttrDefaultKeyProp", typeof(double));
            Assert.AreEqual(expected, Tuple.Create(propInfo.Name, propInfo.PropertyType));
        }

        [TestMethod]
        public void Build_SingleNameAttrDefaultKeyPropertyByNameOfAttr_ReturnCorrespondingWithPropNameAndName()
        {
            //Arrange
            IPropertyInfoBuilder builder = new PropertyInfoBuilder();
            var modelContext = new ModelContext(typeof(TestModel), SchemeKey.Default);
            var valueContext = new ValuesContext(modelContext, "OtherNameDefaultKey");
            //Act
            var propInfo = builder.Build(valueContext);

            //Assert
            var expected = Tuple.Create("SingleNameAttrDefaultKeyProp", typeof(double));
            Assert.AreEqual(expected, Tuple.Create(propInfo.Name, propInfo.PropertyType));
        }

        [TestMethod]
        public void Build_MultipleNameAttrsPropertyByPropName_ReturnCorrespondingWithPropNameAndName()
        {
            //Arrange
            IPropertyInfoBuilder builder = new PropertyInfoBuilder();
            var modelContext = new ModelContext(typeof(TestModel), SchemeKey.Create("AnyKey"));
            var valueContext = new ValuesContext(modelContext, "MultipleNameAttrsProp");
            //Act
            var propInfo = builder.Build(valueContext);

            //Assert
            var expected = Tuple.Create("MultipleNameAttrsProp", typeof(string));
            Assert.AreEqual(expected, Tuple.Create(propInfo.Name, propInfo.PropertyType));
        }

        [TestMethod]
        public void Build_MultipleNameAttrsPropertyByNameOfAttr_ReturnCorrespondingWithPropNameAndName()
        {
            //Arrange
            IPropertyInfoBuilder builder = new PropertyInfoBuilder();
            var modelContext = new ModelContext(typeof(TestModel), SchemeKey.Create("Key2"));
            var valueContext = new ValuesContext(modelContext, "Name2");
            //Act
            var propInfo = builder.Build(valueContext);

            //Assert
            var expected = Tuple.Create("MultipleNameAttrsProp", typeof(string));
            Assert.AreEqual(expected, Tuple.Create(propInfo.Name, propInfo.PropertyType));
        }

        [TestMethod]
        public void Build_MultipleNameAttrsPropertyByNameOfAttrWrongKey_ReturnNull()
        {
            //Arrange
            IPropertyInfoBuilder builder = new PropertyInfoBuilder();
            var modelContext = new ModelContext(typeof(TestModel), SchemeKey.Create("WrongKey"));
            var valueContext = new ValuesContext(modelContext, "Name2");
            //Act
            var propInfo = builder.Build(valueContext);

            //Assert
            Assert.IsNull(propInfo);
        }

    }
}